/*
 * PumpController.c
 *
 *  Created on: May 14, 2009
 *      Author: David
 */
#include "WProgram.h"
#include "LightningDetector.h"
#include <avr/pgmspace.h>
#include <ctype.h>
#include <avr/EEPROM.h>
#include <stdio.h>

/*
 * LightningDetector.c
 *
 *  Created on: August 22, 2009
 *      Author: David
 */
#define VERSION          "Version 1.0 compiled on "__DATE__" at " __TIME__
#define LIGHTNING_LED_PIN         13
#define PUMP_LED_PIN    2
#define TIMEOUT_LED_PIN 3
#define RELAY_PIN       12      //relay on digital 12
#define PHOTO_PIN       0       //input on analog 0
#define ERROR_PIN       9       //analog output for ambient light compensation
#define MAX_SLEW_RATE   5       //limits the rate of compensation for ambient light, minimizes "bouncing"
#define RESET_DELAY     256     //x10 ms after lightning is seen
#define LED_ON_OFF_TIME_MS 250  //blink LED 1/4 sec on, 1/4 sec off
#define LED_ON_OFF_COUNT (16000/LED_ON_OFF_TIME_MS) //loop count for LED blinker

int lastReading = 0;
int thisReading = 0;
//char bar[128];
int errval=128; //half way
int lastErrval=128;
int resetCounter=0;
int strikeCount=0;
boolean inStrike=false; //strike is in progress
int strikeBlinkPass=0;  //pass counter for LED on/off time
int strikeBlinkCount=0; //blink counter for LED on/off time

// subroutine prototypes
void quiesce();

void setup()
  {
  //Set up the serial communications
  Serial.begin(19200);
  Serial.println("");
  Serial.println(VERSION);

  //use the 5v default reference
  analogReference(DEFAULT);
  pinMode(ERROR_PIN,OUTPUT);

  //initialze the sensors
  pinMode(PHOTO_PIN, INPUT);
  digitalWrite(PHOTO_PIN, LOW);

  //initialze the outputs
  pinMode(LIGHTNING_LED_PIN, OUTPUT);  //we'll use the led to indicate detection
  digitalWrite(LIGHTNING_LED_PIN,HIGH); //High is off on the dorkboard
  pinMode(PUMP_LED_PIN, OUTPUT);  //we'll use the led to indicate detection
  digitalWrite(PUMP_LED_PIN,HIGH); //High is off on the dorkboard
  pinMode(TIMEOUT_LED_PIN, OUTPUT);  //we'll use the led to indicate detection
  digitalWrite(TIMEOUT_LED_PIN,HIGH); //High is off on the dorkboard
  pinMode(RELAY_PIN, OUTPUT);  //set up the relay
  digitalWrite(RELAY_PIN,LOW); //off

  //initialize variables
  resetCounter=0;
  thisReading=analogRead(PHOTO_PIN);
  lastReading=thisReading;

  //Ready to loop
  Serial.println("Ready.");
  Serial.println("");
  }

//void blinkLED()
//  {
//  if (strikeBlinkPass-- <=0)
//    {
//    digitalWrite(LED_PIN,!digitalRead(LED_PIN)); //change the state of the LED
//    if (strikeBlinkCount-- <=0)
//      {
//      digitalWrite(LED_PIN,HIGH);         //turn off the LED
//      strikeBlinkPass=LED_ON_OFF_COUNT*3; //start a new blink display
//      strikeBlinkCount=strikeCount*2;     //half for off time, half for on time
//      }
//    else
//      strikeBlinkPass=LED_ON_OFF_COUNT; //start the next blink
//    }
//  }

void loop()
  {
  quiesce();

  Serial.print("\r");
  Serial.print(thisReading);
  Serial.print("  \t/\t");
  Serial.print(errval);
  Serial.print("  \t/\t");
  Serial.print(resetCounter);
  Serial.print("  \t/\t");
  Serial.print(strikeCount);
  Serial.print("  ");

  if (thisReading > (lastReading+5)*1.1) //+5 for when it's really really dark
    {
    digitalWrite(LIGHTNING_LED_PIN, LOW);//turn on the blue LED
    digitalWrite(PUMP_LED_PIN, HIGH);//turn off the green LED
    digitalWrite(RELAY_PIN, HIGH);//turn on the relay
    resetCounter=RESET_DELAY;
    if (!inStrike)
      strikeCount++; //"debounce" the strike
    inStrike=true;
    }
  else
    {
    digitalWrite(PUMP_LED_PIN, LOW);//turn on the green LED
    if (resetCounter>0)
      {
      digitalWrite(TIMEOUT_LED_PIN, LOW);//turn on the RED LED
      resetCounter--;
      }
    else //turn off the LED and relay
      {
      digitalWrite(LIGHTNING_LED_PIN, HIGH);
      digitalWrite(TIMEOUT_LED_PIN, HIGH);//turn off the RED LED
      digitalWrite(RELAY_PIN, LOW);
      inStrike=false;
      }
    }

  lastReading=thisReading;

  //blinkLED();
  }

//Try to keep the input signal quiesced at approximately the midpoint of the range.
//This is done by adjusting the pulse width being sent to the compensation circuit.
//This routine calculates the value of the pulse width.
void quiesce()
    {
    thisReading=analogRead(PHOTO_PIN);

    if ((thisReading>lastReading && errval>lastErrval)
      ||(thisReading<lastReading && errval<lastErrval)
      || errval==lastErrval)
      {
      errval=((thisReading-512))+errval;
      if (errval>(lastErrval+MAX_SLEW_RATE))
        errval=lastErrval+MAX_SLEW_RATE;
      else if (errval<(lastErrval-MAX_SLEW_RATE))
        errval=lastErrval-MAX_SLEW_RATE;
      if (errval<0) errval=0;
      if (errval>255) errval=255;
      lastErrval=errval;
      }
    analogWrite(ERROR_PIN, errval); //write the new value to the compensation circuit
    }


